package com.ywwxhz.lib; import android.media.MediaPlayer; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.webkit.WebChromeClient; import android.webkit.WebView; import android.widget.FrameLayout; import android.widget.VideoView; public class BaseWebChromeClient extends WebChromeClient implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener { boolean mIsVideoFullscreen = false; FrameLayout mVideoViewFrameLayout; CustomViewCallback mVideoViewCallback; Callback mOutCallback; WebView mWebView; View mNonFullscreenVideoLayout; ViewGroup mFullscreenVideoLayout; public interface Callback { void enterFullscreenVideo(); void exitFullscreenVideo(); } class JavaScriptInterface { WebChromeClient mWebChromeClient; public JavaScriptInterface(WebChromeClient webChromeClient) { mWebChromeClient = webChromeClient; } @android.webkit.JavascriptInterface @SuppressWarnings("unused") public void notifyVideoEnd() { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { if (mWebChromeClient != null) { mWebChromeClient.onHideCustomView(); } } }); } } public void init(WebView webview, View nonFullscreenVideoLayout, ViewGroup fullScreenVideoLayout, Callback callback) { mWebView = webview; mNonFullscreenVideoLayout = nonFullscreenVideoLayout; mFullscreenVideoLayout = fullScreenVideoLayout; mOutCallback = callback; webview.addJavascriptInterface(new JavaScriptInterface(this), "_VideoEnabledWebView"); } @Override public void onShowCustomView(View view, CustomViewCallback callback) { if (view instanceof FrameLayout) { // A video wants to be shown FrameLayout frameLayout = (FrameLayout) view; View focusedChild = frameLayout.getFocusedChild(); // Save video related variables mIsVideoFullscreen = true; mVideoViewFrameLayout = frameLayout; mVideoViewCallback = callback; // Hide the non-video view, add the video view, and show it mNonFullscreenVideoLayout.setVisibility(View.INVISIBLE); mFullscreenVideoLayout.addView(mVideoViewFrameLayout, new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); mFullscreenVideoLayout.setVisibility(View.VISIBLE); if (focusedChild instanceof android.widget.VideoView) { // android.widget.VideoView (typically API level <11) VideoView videoView = (VideoView) focusedChild; // Handle all the required events videoView.setOnPreparedListener(this); videoView.setOnCompletionListener(this); videoView.setOnErrorListener(this); } else { // Other classes, including: // - android.webkit.HTML5VideoFullScreen$VideoSurfaceView, // which inherits from android.view.SurfaceView (typically // API level 11-18) // - android.webkit.HTML5VideoFullScreen$VideoTextureView, // which inherits from android.view.TextureView (typically // API level 11-18) // - // com.android.org.chromium.content.browser.ContentVideoView$VideoSurfaceView, // which inherits from android.view.SurfaceView (typically // API level 19+) // Handle HTML5 video ended event only if the class is a // SurfaceView // Test case: TextureView of Sony Xperia T API level 16 // doesn't work fullscreen when loading the javascript below if (mWebView != null && mWebView.getSettings().getJavaScriptEnabled() && focusedChild instanceof SurfaceView) { // Run javascript code that detects the video end and // notifies the Javascript interface String js = "javascript:"; js += "var _ytrp_html5_video_last;"; js += "var _ytrp_html5_video = document.getElementsByTagName('video')[0];"; js += "if (_ytrp_html5_video != undefined && _ytrp_html5_video != _ytrp_html5_video_last) {"; { js += "_ytrp_html5_video_last = _ytrp_html5_video;"; js += "function _ytrp_html5_video_ended() {"; { js += "_VideoEnabledWebView.notifyVideoEnd();"; } js += "}"; js += "_ytrp_html5_video.addEventListener('ended', _ytrp_html5_video_ended);"; } js += "}"; injectJS(mWebView, js); } } // Notify full-screen change if (mOutCallback != null) { mOutCallback.enterFullscreenVideo(); } } } @Override public void onHideCustomView() { // This method should be manually called on video end in all cases // because it's not always called automatically. // This method must be manually called on back key press (from this // class' onBackPressed() method). if (mIsVideoFullscreen) { // Hide the video view, remove it, and show the non-video view mFullscreenVideoLayout.setVisibility(View.INVISIBLE); mFullscreenVideoLayout.removeView(mVideoViewFrameLayout); mNonFullscreenVideoLayout.setVisibility(View.VISIBLE); // Call back (only in API level <19, because in API level 19+ with // chromium webview it crashes) if (mVideoViewCallback != null && !mVideoViewCallback.getClass().getName().contains(".chromium.")) { mVideoViewCallback.onCustomViewHidden(); } // Reset video related variables mIsVideoFullscreen = false; mVideoViewFrameLayout = null; mVideoViewCallback = null; // Notify full-screen change if (mOutCallback != null) { mOutCallback.exitFullscreenVideo(); } } } private void injectJS(WebView webview, String script) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { webview.evaluateJavascript(script, null); } else { webview.loadUrl("javascript:" + script); } } @Override public boolean onError(MediaPlayer arg0, int arg1, int arg2) { return false; } @Override public void onCompletion(MediaPlayer arg0) { onHideCustomView(); } @Override public void onPrepared(MediaPlayer arg0) { } public boolean onBackPressed() { if (mIsVideoFullscreen) { onHideCustomView(); return true; } else { return false; } } }